/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.makcro.sms.services.chat.base.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import org.springframework.transaction.annotation.Transactional;

/**
 * 
 * @author makcro
 */
@Transactional
public abstract class AbstractDAO<T> implements BasicDao<T> {
	@PersistenceContext
	protected EntityManager	entityManager	= null;

	private Class<T>		entityClass;

	public AbstractDAO(Class<T> entityClass) {
		this.entityClass = entityClass;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.makcro.sms.services.chat.base.dao.BasicDao#create(T)
	 */
	@Override
	@Transactional
	public void create(T entity) {
		entityManager.persist( entity );
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.makcro.sms.services.chat.base.dao.BasicDao#edit(T)
	 */
	@Override
	@Transactional
	public void edit(T entity) {
		entityManager.merge( entity );
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.makcro.sms.services.chat.base.dao.BasicDao#delete(T)
	 */
	@Override
	@Transactional
	public void delete(T entity) {
		T entityForDeletiing = entityManager.merge( entity );
		entityManager.remove( entityForDeletiing );
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.makcro.sms.services.chat.base.dao.BasicDao#find(java.lang.Object)
	 */
	@Override
	public T find(Object id) {
		return entityManager.find( entityClass, id );
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.makcro.sms.services.chat.base.dao.BasicDao#findAll()
	 */
	@Override
	public List<T> findAll() {
		TypedQuery<T> typedQuery = buildTypedQuery();
		return typedQuery.getResultList();

	}

	protected TypedQuery<T> buildTypedQuery() {
		CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
		CriteriaQuery<T> query = criteriaBuilder.createQuery( entityClass );
		Root<T> from = query.from( entityClass );
		TypedQuery<T> typedQuery = entityManager.createQuery( query );
		return typedQuery;
	}

	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}

	@Override
	public List<T> findAll(int[] limits) {
		TypedQuery<T> typedQuery = buildTypedQuery();
		typedQuery.setFirstResult( limits[0] );
		typedQuery.setMaxResults( limits[1] );
		return typedQuery.getResultList();
	}

	@Override
	public Long findAllCount() {
		CriteriaBuilder qb = entityManager.getCriteriaBuilder();
		CriteriaQuery<Long> cq = qb.createQuery( Long.class );
		cq.select( qb.count( cq.from( entityClass ) ) );
		return entityManager.createQuery( cq ).getSingleResult();

	}
}
